<template>
  <div class="avatar-uploader" @click="editCropper">
    <img v-if="modelValue" :src="avatarUrl" class="avatar-image" />
    <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
    <el-dialog
      :width="width"
      title="修改头像"
      v-model="open"
      append-to-body
      @opened="modalOpened"
      @close="closeDialog"
    >
      <el-row>
        <el-col :xs="24" :md="12" :style="{ height: '350px' }">
          <vue-cropper
            ref="cropperRef"
            :img="options.img"
            :info="true"
            :autoCrop="options.autoCrop"
            :autoCropWidth="options.autoCropWidth"
            :autoCropHeight="options.autoCropHeight"
            :fixedBox="options.fixedBox"
            :outputType="options.outputType"
            @realTime="realTime"
            v-if="visible"
          />
        </el-col>
        <el-col :xs="24" :md="12" :style="{ height: '350px' }">
          <div class="avatar-upload-preview">
            <img :src="options.previews.url" :style="options.previews.img" />
          </div>
        </el-col>
      </el-row>
      <br />
      <template #footer>
        <el-row>
          <el-col :lg="2" :md="2">
            <el-upload
              action="#"
              :http-request="requestUpload"
              :show-file-list="false"
              :before-upload="beforeUpload"
            >
              <el-button type="warning">
                <el-icon><Upload /></el-icon>
                <span class="ml-2">选择</span>
              </el-button>
            </el-upload>
          </el-col>
          <el-col :lg="{ span: 1, offset: 2 }" :md="2">
            <el-button @click="changeScale(1)">
              <el-icon><Plus /></el-icon>
            </el-button>
          </el-col>
          <el-col :lg="{ span: 1, offset: 1 }" :md="2">
            <el-button @click="changeScale(-1)">
              <el-icon><Minus /></el-icon>
            </el-button>
          </el-col>
          <el-col :lg="{ span: 1, offset: 1 }" :md="2">
            <el-button @click="rotateLeft()">
              <el-icon><RefreshLeft /></el-icon>
            </el-button>
          </el-col>
          <el-col :lg="{ span: 1, offset: 1 }" :md="2">
            <el-button @click="rotateRight()">
              <el-icon><RefreshRight /></el-icon>
            </el-button>
          </el-col>
          <el-col :lg="{ span: 2, offset: 6 }" :md="2">
            <el-button type="primary" @click="uploadImg()">提 交</el-button>
          </el-col>
        </el-row>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import { uploadUsersAvatar } from '@/api/system/users'
import { Plus, Minus, Upload, RefreshLeft, RefreshRight } from '@element-plus/icons-vue'
import to from '@/utils/to'
import { systemBaseUrl } from '@/api/config/base.js'
import { getToken } from '@/utils/auth'

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  userId: {
    type: [Number, String],
    default: ''
  },
  width: {
    type: String,
    default: '800px'
  }
})

const emits = defineEmits(['update:modelValue', 'success'])
const proxy = inject('proxy')

const open = ref(false)
const visible = ref(false)
const cropperRef = ref(null)
const baseApiUrl = import.meta.env.VITE_APP_BASE_API
const uploadLoading = ref(false)

const avatarUrl = computed(() => {
  if (props.modelValue && props.modelValue.startsWith('http')) {
    return props.modelValue
  } else if (props.modelValue) {
    return baseApiUrl + props.modelValue
  }
  return ''
})

// 图片裁剪数据
const options = reactive({
  img: props.modelValue ? (props.modelValue.startsWith('http') ? props.modelValue : baseApiUrl + props.modelValue) : '',
  autoCrop: true,
  autoCropWidth: 200,
  autoCropHeight: 200,
  fixedBox: true,
  outputType: 'png',
  previews: {}
})

// 监听modelValue变化，更新图片显示
watch(() => props.modelValue, (newVal) => {
  if (newVal) {
    if (newVal.startsWith('http')) {
      // 如果是http链接，直接使用
      options.img = newVal
    } else {
      // 否则拼接baseApiUrl
      options.img = baseApiUrl + newVal
    }
  } else {
    options.img = ''
  }
}, { immediate: true })

/** 编辑头像 */
function editCropper() {
  open.value = true
}

/** 打开弹出层结束时的回调 */
function modalOpened() {
  visible.value = true
}

/** 覆盖默认上传行为 */
function requestUpload() {}

/** 向左旋转 */
function rotateLeft() {
  cropperRef.value?.rotateLeft()
}

/** 向右旋转 */
function rotateRight() {
  cropperRef.value?.rotateRight()
}

/** 图片缩放 */
function changeScale(num) {
  num = num || 1
  cropperRef.value?.changeScale(num)
}

/** 上传预处理 */
function beforeUpload(file) {
  if (file.type.indexOf('image/') == -1) {
    proxy.$modal.msgError('文件格式错误，请上传图片类型,如：JPG，PNG后缀的文件。')
  } else {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => {
      options.img = reader.result
    }
  }
}

// 上传图片到公共上传接口
async function uploadToCommon(blob) {
  try {
    let formData = new FormData()
    formData.append('file', blob)
    
    // 直接使用axios创建上传请求
    const response = await fetch(import.meta.env.VITE_APP_BASE_API + '/common/upload', {
      method: 'POST',
      body: formData,
      headers: {
        'Authorization': 'Bearer ' + getToken()
      }
    }).then(res => res.json())
    
    if (response.code === 200 && response.fileName) {
      return response.fileName
    } else {
      throw new Error(response.msg || '上传失败')
    }
  } catch (error) {
    throw error
  }
}

/** 上传图片 */
async function uploadImg() {
  if (uploadLoading.value) return
  uploadLoading.value = true
  
  try {
    cropperRef.value?.getCropBlob(async (blob) => {
      try {
        // 无论是否有userId，都直接上传到公共上传接口
        const fileName = await uploadToCommon(blob)
        
        // 更新头像URL
        emits('update:modelValue', fileName)
        emits('success', fileName)
        
        open.value = false
        visible.value = false
        proxy.$modal.notifySuccess('头像上传成功')
      } catch (error) {
        proxy.$modal.msgError(error?.message || '上传失败')
      } finally {
        uploadLoading.value = false
      }
    })
  } catch (error) {
    proxy.$modal.msgError(error?.message || '裁剪失败')
    uploadLoading.value = false
  }
}

/** 实时预览 */
function realTime(data) {
  options.previews = data
}

/** 关闭窗口 */
function closeDialog() {
  visible.value = false
}
</script>

<style lang="scss" scoped>
.avatar-uploader {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 120px;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader:hover {
  border-color: var(--el-color-primary);
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 120px;
  height: 120px;
  text-align: center;
  line-height: 120px;
}

.avatar-image {
  height: 100%;
  width: auto;
  display: block;
  max-width: 100%;
  border-radius: 6px;
}

.avatar-upload-preview {
  position: absolute;
  top: 50%;
  transform: translate(50%, -50%);
  width: 200px;
  height: 200px;
  border-radius: 50%;
  box-shadow: 0 0 4px #ccc;
  overflow: hidden;
}
</style> 